package com.kkwrite.regimen.provider.controller.shop;

import static com.kkwrite.regimen.common.constant.Constant.BOOLEAN_STRING_FALSE;
import static com.kkwrite.regimen.common.constant.Constant.BOOLEAN_STRING_TRUE;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import springfox.documentation.annotations.ApiIgnore;

import com.kkwrite.regimen.common.constant.SortTypeEnum;
import com.kkwrite.regimen.common.entity.dto.OutDTO;
import com.kkwrite.regimen.common.entity.dto.shop.EditShopInDTO;
import com.kkwrite.regimen.common.entity.dto.shop.EditShopOutDTO;
import com.kkwrite.regimen.common.entity.dto.shop.InsertShopEmployeeInDTO;
import com.kkwrite.regimen.common.entity.dto.shop.InsertShopEmployeeOutDTO;
import com.kkwrite.regimen.common.entity.dto.shop.InsertShopOutDTO;
import com.kkwrite.regimen.common.entity.dto.shop.PageableItemDTO;
import com.kkwrite.regimen.common.entity.dto.shop.PageableShopIncomeDTO;
import com.kkwrite.regimen.common.entity.dto.shop.ShopDetailDTO;
import com.kkwrite.regimen.common.entity.dto.user.PageableUserDTO;
import com.kkwrite.regimen.provider.config.SystemConfig;
import com.kkwrite.regimen.provider.exception.DBNullException;
import com.kkwrite.regimen.provider.exception.ServiceException;
import com.kkwrite.regimen.provider.repository.RegShopRepository;
import com.kkwrite.regimen.provider.service.shop.ShopService;
import com.kkwrite.regimen.provider.util.TokenUtil;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;

/**
 * 店铺服务
 *
 * @author Soosky Wang
 * @version 1.0.0
 * @date 2018年7月21日 下午4:12:18
 */
@Api(value = "店铺模块")
@RestController
@RequestMapping("/shop")
public class ShopController {

    private static final Logger logger = LoggerFactory.getLogger(ShopController.class);
    private static final Pattern REG_PHONE_NUM = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(17[0-9])|(18[0,5-9]))\\d{8}$");

    @Resource(name = "shopService")
    private ShopService shopService;

    @Resource(name = "tokenUtil")
    private TokenUtil tokenUtil;

    @Resource(name = "systemConfig")
    private SystemConfig config;

    @Resource(name = "regShopRepository")
    private RegShopRepository regShopRepository;

    @Resource
    private RestTemplate restTemplate;

    @PostMapping(value = "/uploadqrcode")
    @HystrixCommand(fallbackMethod = "uploadQrcodeError")
    @ApiOperation(value = "上传分享二维码图片接口", notes = "name=picture")
    public OutDTO uploadQrcode(@ApiIgnore MultipartFile picture, @ApiIgnore @RequestHeader String token) throws IOException {
        String shopId = (String) tokenUtil.getValue(token, TokenUtil.TokenKeyEnum.SHOP_ID);
        if (shopId == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Assert.notNull(picture, "入参不合法");
        if (picture.isEmpty()) {
            throw new IllegalArgumentException("入参不合法");
        }
        if (!picture.getContentType().startsWith("image/")) {
            throw new RuntimeException("图片格式不正确！");
        }
        String qrcodeFileName = generateQrcodeFileName();
        FileUtils.copyInputStreamToFile(picture.getInputStream(),
                new File(config.getQrcodeFilePath() + "/" + qrcodeFileName));
        return OutDTO.of(BOOLEAN_STRING_TRUE, "OK", "OK", "/qrcode-images/" + qrcodeFileName);
    }

    public OutDTO uploadQrcodeError(MultipartFile picture, String token, Throwable t) {
        return OutDTO.of(BOOLEAN_STRING_FALSE, "上传分享二维码图片异常，异常信息：" + t.getMessage());
    }

    @GetMapping(value = "/getwxqrcodeunlimit")
    @HystrixCommand(fallbackMethod = "generateQrcodeError", commandProperties = {
            @HystrixProperty(name = "execution.timeout.enabled", value = "false")
    })
    @ApiOperation(value = "生成用户小程序分享二维码接口")
    @ApiImplicitParam(name = "page", value = "需要扫码打开的页面，需要url encode，如果为空默认跳主页面",
            paramType = "query", dataType = "string")
    public OutDTO generateQrcode(@RequestParam(required = false) String page, @ApiIgnore @RequestHeader String token) {
        String shopIdString = (String) tokenUtil.getValue(token, TokenUtil.TokenKeyEnum.SHOP_ID);
        if (shopIdString == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        String qrcodePath;
        try {
            qrcodePath = shopService.queryQrcodePath(shopIdString);
        } catch (DBNullException e) {
            throw new RuntimeException("该店铺不存在");
        }
        if (StringUtils.isBlank(qrcodePath)) {
            if (StringUtils.isBlank(page)) {
                page = "";
            }
            String serviceUrl = "http://reg-consumer/user/shopgetwxqrcode?page=" + page + "&shopId=" + shopIdString + "&width=1280";
            OutDTO out = restTemplate.getForObject(serviceUrl, OutDTO.class);
            if (out != null && out.getSuccess().equals(BOOLEAN_STRING_TRUE)) {
                qrcodePath = (String) out.getData();
                try {
                    shopService.saveQrcodePath(qrcodePath, shopIdString);
                } catch (DBNullException e) {
                    throw new RuntimeException("店铺不存在");
                }
            } else {
                String message = "调用服务异常！";
                if (out != null) {
                    message = out.getMsg();
                }
                throw new RuntimeException(message);
            }
        }
        return OutDTO.of(BOOLEAN_STRING_TRUE, "OK", "OK", qrcodePath);
    }

    public OutDTO generateQrcodeError(String page, String token, Throwable t) {
        return OutDTO.of(BOOLEAN_STRING_FALSE, "生成店铺分享二维码异常！异常信息：" + t.getMessage(), null, page);
    }

    @ApiOperation(value = "根据店铺 id 查询店铺详情")
    @GetMapping("/getshopdetail")
    public OutDTO<ShopDetailDTO> getShopDetail(HttpServletRequest request) {
        Object obj = tokenUtil.getValue(request.getHeader("token"), TokenUtil.TokenKeyEnum.SHOP_ID);
        if (obj == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Long shopId = Long.valueOf((String) obj);
        OutDTO<ShopDetailDTO> outDTO = new OutDTO<>();
        try {
            ShopDetailDTO shopDetailDTO = shopService.getShopDetail(shopId);
            outDTO.setSuccess("true");
            outDTO.setData(shopDetailDTO);

            return outDTO;
        } catch (ServiceException e) {
            e.printStackTrace();

            return new OutDTO<ShopDetailDTO>("failed", e.getMessage());
        }
    }

    @ApiOperation(value = "店铺项目列表分页接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "获取第page页数据", required = true, allowableValues = "[0, infinity]", paramType = "query", dataType = "Long"),
            @ApiImplicitParam(name = "size", value = "每页size条记录", required = true, allowableValues = "[1, infinity]", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "sortType", value = "按时间排序的排序类型", defaultValue = "2", allowableValues = "{1, 2}", paramType = "path", dataType = "int")})
    @GetMapping("/getItem")
    public OutDTO<PageableItemDTO> queryItemByShopId(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @PathVariable(required = false) Integer sortType,
            HttpServletRequest request) {
        Object obj = tokenUtil.getValue(request.getHeader("token"),
                TokenUtil.TokenKeyEnum.SHOP_ID);
        if (obj == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Long shopId = Long.valueOf((String) obj);
        if (page == null || page < 0 || size == null || size < 1) {
            return new OutDTO<>("false", "入参不合法");
        }
        if (!SortTypeEnum.isSortType(sortType)) {
            sortType = 2;
        }
        OutDTO<PageableItemDTO> outDTO = new OutDTO<>();
        try {
            PageableItemDTO pageableItemDTO = shopService.queryItemByShopId(
                    page, size, shopId, sortType);
            outDTO.setSuccess("true");
            outDTO.setData(pageableItemDTO);
            return outDTO;
        } catch (ServiceException e) {
            logger.error(e.getMessage(), e);
            return new OutDTO<>("failed", e.getMessage());
        }
    }

    @GetMapping("/queryUserByInviterIdShop")
    @ApiOperation(value = "查看店铺邀请明细接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "获取第page页数据", required = true, allowableValues = "[0, infinity]", paramType = "query", dataType = "Long"),
            @ApiImplicitParam(name = "size", value = "每页size条记录", required = true, allowableValues = "[1, infinity]", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "sortType", value = "按时间排序的排序类型", defaultValue = "2", allowableValues = "{1, 2}", paramType = "path", dataType = "int")})
    public OutDTO queryUserByInviterId(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer size,
            @PathVariable(required = false) Integer sortType,
            HttpServletRequest request) {
        Object obj = tokenUtil.getValue(request.getHeader("token"),
                TokenUtil.TokenKeyEnum.SHOP_ID);
        if (obj == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Long shopId = Long.valueOf((String) obj);
        if (page == null || page < 0 || size == null || size < 1) {
            return new OutDTO<>("false", "入参不合法");
        }
        if (!SortTypeEnum.isSortType(sortType)) {
            sortType = 2;
        }
        OutDTO<PageableUserDTO> outDTO = new OutDTO<>();
        try {
            PageableUserDTO pageableUserDTO = shopService
                    .queryUserByInviterIdShop(page, size, shopId, sortType);
            outDTO.setSuccess("true");
            outDTO.setData(pageableUserDTO);
            return outDTO;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new OutDTO<>("failed", e.getMessage());
        }
    }

    @GetMapping("/getShopIncome")
    @ApiOperation(value = "查询店铺收益明细")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "获取第page页数据", required = true, allowableValues = "[0, infinity]", paramType = "query", dataType = "Long"),
            @ApiImplicitParam(name = "size", value = "每页size条记录", required = true, allowableValues = "[1, infinity]", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "sortType", value = "按时间排序的排序类型", defaultValue = "2", allowableValues = "{1, 2}", paramType = "path", dataType = "int")})
    public OutDTO getShopIncome(@RequestParam(required = false) Integer page,
                                @RequestParam(required = false) Integer size,
                                @RequestParam(required = false) Integer sortType,
                                HttpServletRequest request) {
        Object obj = tokenUtil.getValue(request.getHeader("token"), TokenUtil.TokenKeyEnum.SHOP_ID);
        if (obj == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Long shopId = Long.valueOf((String) obj);
        if (page == null || page < 0 || size == null || size < 1) {
            return new OutDTO<>("false", "入参不合法");
        }
        if (!SortTypeEnum.isSortType(sortType)) {
            sortType = 2;
        }
        OutDTO<PageableShopIncomeDTO> outDTO = new OutDTO<>();
        try {
            PageableShopIncomeDTO pageableShopIncomeDTO = shopService
                    .queryShopIncome(page, size, shopId, sortType);
            outDTO.setSuccess("true");
            outDTO.setData(pageableShopIncomeDTO);
            return outDTO;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new OutDTO<>("failed", e.getMessage());
        }
    }

    @PostMapping("/editShop")
    @ApiOperation(value = "编辑店铺资料")
    @ApiImplicitParam(name = "inDTO", value = "提交数据", required = true, paramType = "body", dataType = "EditShopInDTO")
    public OutDTO editShop(@RequestBody EditShopInDTO inDto, HttpServletRequest request) {
        Object obj = tokenUtil.getValue(request.getHeader("token"), TokenUtil.TokenKeyEnum.SHOP_ID);
        if (obj == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Long shopId = Long.valueOf((String) obj);
        inDto.setShopId(shopId);
        EditShopOutDTO editShopOutDTO = shopService.editShop(inDto);
        OutDTO outDto = new OutDTO();
        outDto.setSuccess(editShopOutDTO.getSuccess());
        outDto.setMsg(editShopOutDTO.getMsg());
        return outDto;
    }


    @PostMapping("/insertShop")
    @ApiOperation(value = "新增店铺")
    @ApiImplicitParam(name = "inDTO", value = "提交数据", required = true, paramType = "body", dataType = "EditShopInDTO")
    public OutDTO insertShop(@RequestBody EditShopInDTO inDto, HttpServletRequest request) {
        InsertShopOutDTO insertShopOutDTO = shopService.insertShop(inDto);
        OutDTO outDto = new OutDTO();
        outDto.setSuccess(insertShopOutDTO.getSuccess());
        outDto.setMsg(insertShopOutDTO.getMsg());
        Map map = new HashMap();
        map.put("shopId", insertShopOutDTO.getShopId());
        outDto.setData(map);
        return outDto;
    }

    @PostMapping(value = "/uploadShopPicture")
    @ApiOperation(value = "上传店铺图片", notes = "name=picture")
    public OutDTO uploadShopPicture(@ApiIgnore MultipartFile picture, HttpServletRequest request) throws IOException {
        Object obj = tokenUtil.getValue(request.getHeader("token"), TokenUtil.TokenKeyEnum.SHOP_ID);
        if (obj == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
        }
        Assert.notNull(picture, "入参不合法");
        if (picture.isEmpty()) {
            throw new IllegalArgumentException("入参不合法");
        }
        if (!request.getServletContext().getMimeType(picture.getOriginalFilename()).startsWith("image/")) {
            throw new RuntimeException("图片格式不正确！");
        }
        String pictrueFileName = generateQrcodeFileName();
        FileUtils.copyInputStreamToFile(picture.getInputStream(),
                new File(config.getShopPicturePath() + "/" + pictrueFileName));
        String accessShoPicturePath = "/shop-images/" + pictrueFileName;
        return OutDTO.of(BOOLEAN_STRING_TRUE, "OK", "OK", accessShoPicturePath);
    }

    @PostMapping(value = "/saveShopEmployee")
    @ApiOperation(value = "新增店铺账号")
    @ApiImplicitParam(name = "inDTO", value = "提交数据", required = true, paramType = "body", dataType = "InsertShopEmployeeInDTO")
    public OutDTO saveShopEmployee(@RequestBody InsertShopEmployeeInDTO inDto, HttpServletRequest request) throws IOException {
    	/*if(inDto.getShopId()==null){
    		Object obj = tokenUtil.getValue(request.getHeader("token"), TokenUtil.TokenKeyEnum.SHOP_ID);
    		if (obj == null) {
    			return OutDTO.of(BOOLEAN_STRING_FALSE, "002", "token invalid");
    		}
    		Integer shopId = Integer.valueOf((String) obj);
    		inDto.setShopId(shopId);
    	}*/
        if (inDto.getShopId() == null) {
            return new OutDTO("filed", "店铺Id不能为空");
        }
        if (inDto.getEmployeeName() == null) {
            return new OutDTO("filed", "用户名不为空");
        }
        if (inDto.getPassword() == null) {
            return new OutDTO("filed", "密码不能为空");
        }
        if (inDto.getPhoneNum() == null) {
            return new OutDTO("filed", "电话号码不能为空");
        }
        Matcher m = REG_PHONE_NUM.matcher(inDto.getPhoneNum());
        if (!m.matches()) {
            return new OutDTO("filed", "电话号码格式不正确");
        }
        if (!regShopRepository.findById(Long.valueOf(inDto.getShopId() + "")).isPresent()) {
            return new OutDTO("filed", "请核实店铺Id是否存在");
        }
        InsertShopEmployeeOutDTO insertShopEmployeeOutDTO = shopService.saveShopEmployee(inDto);
        return new OutDTO("success", insertShopEmployeeOutDTO.getMsg());

    }

    private String generateQrcodeFileName() {
        int num = UUID.randomUUID().toString().hashCode();
        if (num < 0) {
            num = -num;
        }
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
                + num
                + ".png";
    }
}
